package test

import (
	"context"
	"log"
	"sync"

	"go.mongodb.org/mongo-driver/v2/bson"
	"go.mongodb.org/mongo-driver/v2/mongo"
	"go.mongodb.org/mongo-driver/v2/mongo/options"
)

type AnyValue bson.M

func (r *AnyValue) Reset() {
	*r = AnyValue(make(bson.M, 0))
}

type MapPool[T any] struct {
	pool sync.Pool
}

func NewMapPool[T any]() MapPool[T] {
	return MapPool[T]{pool: sync.Pool{New: func() any {
		var t T
		return t
	}}}
}
func (p *MapPool[T]) Get() T {
	return p.pool.Get().(T)
}
func (p *MapPool[T]) Put(t T) {
	p.pool.Put(t)
}

var defaultPool = NewMapPool[AnyValue]()

func getAllDocWithFullSchema(ctx context.Context, collection *mongo.Collection, filter bson.M, opts ...options.Lister[options.FindOptions]) ([]AnyValue, error) {
	// 首先获取所有可能的字段
	resultDecoder, err := docStruct(collection, ctx)
	if err != nil {
		return nil, err
	}
	// 构建查询
	cursor, err := collection.Find(ctx, filter, opts...)
	if err != nil {
		return nil, err
	}

	defer cursor.Close(ctx)
	values := make([]AnyValue, 0, cursor.RemainingBatchLength())

	for cursor.Next(ctx) {
		doc, err := resultDecoder.DecodeDocument(cursor.Current)
		if err != nil {
			log.Fatal(err)
		}

		values = append(values, doc)
	}

	if err := cursor.Err(); err != nil {
		return nil, err
	}

	return values, nil
}
func getAllDocWithFullSchema2(ctx context.Context, collection *mongo.Collection, filter bson.M, opts ...options.Lister[options.FindOptions]) ([]AnyValue, error) {
	// 首先获取所有可能的字段
	resultDecoder, err := docStruct(collection, ctx)
	if err != nil {
		return nil, err
	}
	// 构建查询
	cursor, err := collection.Find(ctx, filter, opts...)
	if err != nil {
		return nil, err
	}

	defer cursor.Close(ctx)

	var values []AnyValue

	err = cursor.All(ctx, &values)
	if err != nil {
		return nil, err
	}

	if err := cursor.Err(); err != nil {
		return nil, err
	}

	for i, value := range values {
		for _, field := range resultDecoder.FieldNames {
			if _, exists := value[field]; !exists {
				value[field] = nil
			}
		}

		values[i] = value
	}

	return values, nil
}
func getAllDocNormal(ctx context.Context, collection *mongo.Collection, filter bson.M, opts ...options.Lister[options.FindOptions]) ([]AnyValue, error) {
	// 构建查询
	cursor, err := collection.Find(ctx, filter, opts...)
	if err != nil {
		return nil, err
	}

	defer cursor.Close(ctx)

	var values []AnyValue

	err = cursor.All(ctx, &values)
	if err != nil {
		return nil, err
	}

	if err := cursor.Err(); err != nil {
		return nil, err
	}

	return values, nil
}
func docStruct(collection *mongo.Collection, background context.Context) (ResultDecoder, error) {
	// 使用$objectToArray将文档转换为字段数组
	pipeline := mongo.Pipeline{
		{{Key: "$project", Value: bson.M{
			"fields": bson.M{"$objectToArray": "$$ROOT"},
		}}},
		{{Key: "$unwind", Value: "$fields"}},
		{{Key: "$group", Value: bson.M{
			"_id":        nil,
			"fieldNames": bson.M{"$addToSet": "$fields.k"},
		}}},
	}

	cursor, err := collection.Aggregate(background, pipeline)
	if err != nil {
		panic(err)
	}

	defer cursor.Close(background)

	var result ResultDecoder
	if cursor.Next(background) {
		err = cursor.Decode(&result)
		if err != nil {
			return result, err
		}
	}

	return result, nil
}

type ResultDecoder struct {
	FieldNames []string `bson:"fieldNames"`
}

func (d *ResultDecoder) DecodeDocument(doc bson.Raw) (AnyValue, error) {
	result := defaultPool.Get()
	defer defaultPool.Put(result)
	defer result.Reset()
	//
	// 使用标准解码器解码文档
	err := bson.Unmarshal(doc, &result)
	if err != nil {
		return nil, err
	}
	// 确保所有已知字段都存在
	for _, field := range d.FieldNames {
		if _, exists := result[field]; !exists {
			result[field] = nil
		}
	}

	return result, nil
}
